/**
 * 
 */
package com.mas.session.state;

import java.util.Map;

import jade.lang.acl.ACLMessage;

import com.mas.common.AgentUtil;
import com.mas.common.Consts.Response;
import com.mas.resource.ResourceAllocator;
import com.mas.resource.ResourceInfo;
import com.mas.session.MonitorSession;
import com.mas.session.Session;
import com.mas.strategey.Proposal;

/**
 * this class is being called only after new proposal is being sent by the other
 * agent. this new proposal is being sent because the other agent does not
 * accept my proposal and he offers this new proposal
 * 
 * @author Elad Ben Ami
 * 
 */
public class NewProposalProcessor extends AbstractState {
	private Proposal proposal;

	public NewProposalProcessor(Session session) {
		super(session);
	}

	public void processNewProposal(ACLMessage message) {


		Response strategyResult = session.getStrategy().decide(proposal);

		
		if (strategyResult == Response.REJECT) {
			RejectExitSenderState state = (RejectExitSenderState) this.session
					.assignState(RejectExitSenderState.class.getName());
			state.setProposal(proposal);
			state.sendRejectProposalResponse(message);
		} else if (strategyResult == Response.ACCEPT) {
			// check if this agent is the monitor
			if (AgentUtil.isAgentMonitor(session.getAgent())) {
				allocateResources(message); // allocate the resources
			}
			AcceptNewProposalSenderState state = (AcceptNewProposalSenderState) this.session
					.assignState(AcceptNewProposalSenderState.class.getName());
			state.setProposal(proposal);
			state.sendAcceptNewProposal(message);
		} else if (strategyResult == Response.PROPOSE_COUNTER) {
			CreateCounterProposal state = (CreateCounterProposal) this.session
					.assignState(CreateCounterProposal.class.getName());
			this.session.setCurrentState(state);
			state.setProposal(proposal);
			this.session.offerNewProposal(message);
		}
	}

	private void allocateResources(ACLMessage message) {
		Map mapResourceAllocator = ((MonitorSession) this.session)
				.getMonitorResourceAgent().getMapResourceAllocator();

		ResourceInfo[] resourceInfos = proposal.getResourceInfos();

		for (int i = 0; i < resourceInfos.length; i++) {
			ResourceInfo curResourceInfo = resourceInfos[i];
			if (!mapResourceAllocator.containsKey(curResourceInfo
					.getResourceName())) {
				assignFailureState(message, "Error, resource:"
						+ curResourceInfo.getResourceName() + " not found");
				return;
			}

			ResourceAllocator resourceAllocator = (ResourceAllocator) mapResourceAllocator
					.get(curResourceInfo.getResourceName());

			if (!resourceAllocator.allocateResource(curResourceInfo
					.getRequiredUsage())) {
				assignFailureState(message, "Error, allocation of resource:"
						+ curResourceInfo.getResourceName()
						+ " failed. current Resource usage:"
						+ curResourceInfo.getResourceCurrentUsage());
				return;
			}

		}
	}

	/**
	 * @param proposal
	 *            the proposal to set
	 */
	public void setProposal(Proposal proposal) {
		this.proposal = proposal;
	}

	/**
	 * @return the proposal
	 */
	public Proposal getProposal() {
		return proposal;
	}

}
